<!DOCTYPE html>
<html manifest="editor.appcache">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>欢迎大家使用WebGL中文网为您精心研发的在线编辑系统</title>
		<link rel="stylesheet" href="../js/codemirror/codemirror.css">
		<script src="../js/codemirror/codemirror.js"></script>
		<script src="../js/codemirror/mode/xml.js"></script>
		<script src="../js/codemirror/mode/javascript.js"></script>
		<script src="../js/codemirror/mode/css.js"></script>
		<script src="../js/codemirror/mode/htmlmixed.js"></script>
		<script src="../js/rawinflate.js"></script>
		<script src="../js/rawdeflate.js"></script>
		<script src="../js/esprima.js"></script>
		<style>
			@font-face {

				font-family: 'inconsolata';
				src: url('files/inconsolata.woff') format('woff');
				font-weight: normal;
				font-style: normal;

			}

			html, body {

				height: 100%;

			}

			body {

				margin: 0px;
				overflow: hidden;

				font-family: Arial;

			}

			a {

				color: #ffffff;

			}

			h1 {

				font-size: 20px;
				margin-top: 0px;

			}

			.button {

				font-size: 10px;
				text-transform: uppercase;
				text-decoration: none;

				color: rgb(80,80,80);
				border: transparent;
				background-color: rgb(235,235,235);

				margin: 2px;
				padding: 8px 10px;

				cursor: pointer;

			}

			.button:hover {

				color: rgb(235,235,235);
				background-color: rgb(80,80,80);

			}

			.button path {

				stroke: rgb(80,80,80);

			}

			.button:hover path {

				stroke: rgb(235,235,235);

			}

			#preview {

				position: absolute;
				left: 0px;
				top: 0px;
				width: 100%;
				height: 100%;

			}

			#editor {

				position: absolute;
				width: 100%;
				height: 100%;

			}

			#editor .CodeMirror {

				height: 100%;
				font-family: inconsolata;
				font-size: 16px;
				background-color: rgba(255,255,255,0.85);

				-webkit-transform: translateZ(0); /* Workaround for OSX antialias issue */

			}

			#editor .CodeMirror-scroll {

				height: 100%;

			}

			#editor .CodeMirror div.CodeMirror-selected {

				background: rgba(0,0,0,0.1);

			}

			#editor .CodeMirror-focused div.CodeMirror-selected {

				background: rgba(0,0,255,0.1);

			}

			#editor .CodeMirror .errorLine {

				background: rgba(255,0,0,0.25);

			}

			#editor .CodeMirror .esprima-error {

				color: #f00;
				text-align: right;
				padding: 0px 20px;

			}

			#toolbar {

				position: absolute;
				top: 15px;
				right: 30px;
				text-align: right;

			}

			#popup {

				position: absolute;
				color: rgb(235,235,235);
				padding: 20px 20px 20px 20px;
				background-color: rgb(80,80,80);

			}

		</style>
	</head>
	<body>
		<div id="preview"></div>
		<div id="editor"></div>
		<div id="toolbar"></div>
		<div id="popup"></div>
		<script>

			window.URL = window.URL || window.webkitURL;

			// deflate

			var decode = function ( string ) {

				return RawDeflate.inflate( window.atob( string ) );

			};

			var encode = function ( string ) {

				return window.btoa( RawDeflate.deflate( string ) );

			};

			//

			var defaultCode = decode( 'rVbbbttGEH0rQAH9hy3zEApglnbdoIV1AVpXcQLEqGHLMPq4JkfUuuSS3V1adgx9U5/7EX3s/3T2QoqUBSQBSggSuXNm5uzMmaWm3/3629ny98sFWeuymI+m5ocUTOSzEERoFoBl8xHBa6q5LmA+TdyvWytBM5KumVSgZ2GjV29+Cr1J6acWZq67Knsiz92juUomcy5OyVH9OBkY7lj6Ry6rRmRv0qqo5Cl5dWSvIax6ALkqqs0pWfMsA7Gzbh2FxHOYJm4bU0NiPhpNVSp5rYmS6SykNLlXiV5LAHqvQtygs84PwTKmad7wPWCLxDuT94FJkrISJIuJSkFATCSIDCTISQcoQa0no8DcanjUjYSJ8+aC62jsgEzwkmkwj/Z51YhU80p4ENaz23KbgcyIgA1Zvr9aLOgt3J1/vPKWNmgfTbFv1/wTRGTDRVZtKBcC5C3P9DoeLL0Hnq816YXIqrQpQWhqikpZXWPIszUvsmgXPavKRQEG1fdMku7WlWnA+RKkqgG3+QBn1hqRH4/il/xIcoBgTI7xg0rp53NJaF0pbopHP2G+H/pisk0akLg2K7bsHch0KocKFS+fhoRxXuDcWyLy9gjZnpgvQ8XwGAVBF8X3GgM45w8ly+FG80LRomLZ0pmj0ONUwuh9nYexaIoibtsf6XEXcDdS21YlncRQOpKzYsD2AnX3C1M8vfDW6Llk9anPt+2VrVXpC/eoq0PcpRjvVZOyDIVg3fu0eq33zUPc4gEF8pErjX4yIq9x2yjJ1zGpxK0FXdmFmKxYocDEC4JUAqa++dCKeotVdtNUM8kQ0Y3KDjkKntGzxeAG7LR0RTXjFASBXnNFJdTohdbjSbe2kawm7dJ2YvIFJpCvTxczsgStXBrujebcOHdsg8AcIKY8xiMOXaowPo7fjqnAEFH49zf/fBsegBoGBniyA/71bzimWLk6OjYOW8N2eFQMi2h3uTcYzM4bMv2yGXsxWE2N24NLWd2DTYnKkvzxfzxutnunX3cs2o7h60fkMEz3ZwNK/2xh6PDOdCZq3cghYu4mas9rfy51+YO+oHw+Jyc/OF4x9BHLuLf0NLPa8I+mq3xlG+oUNUNFYazAic+7Gst1L5R5XnaHxpWNdItrNRe5lSOYydiP+/1Xxj0rWFkvq0WWw+eDn3xl8AsuZSUhO0C+V0YBkKkbKygTSTZgVT3qv2wT9xrHt7r90/If' );

			var documents = [ { filename: 'Untitled', filetype: 'text/plain', autoupdate: true, code: defaultCode } ];

			//if ( localStorage.codeeditor !== undefined ) {
				//documents = JSON.parse( localStorage.codeeditor );
			//}

			if ( window.location.hash ) {

				var hash = window.location.hash.substr( 1 );
				var version = hash.substr( 0, 2 );

				if ( version == 'A/' ) {

					alert( 'That shared link format is no longer supported.' );

				} else if ( version == 'B/' ) {

					documents[ 0 ].code = decode( hash.substr( 2 ) );

				}

			}

			// preview

			var preview = document.getElementById( 'preview' );

			// editor

			var interval;

			var editor = CodeMirror( document.getElementById( 'editor' ), {

				value: documents[ 0 ].code,
				mode: 'text/html',
				lineNumbers: true,
				matchBrackets: true,
				indentWithTabs: true,
				tabSize: 4,
				indentUnit: 4

			} );

			editor.on( 'change', function() {

				buttonSave.style.display = '';
				buttonDownload.style.display = 'none';

				if ( documents[ 0 ].autoupdate === false ) return;

				clearTimeout( interval );
				interval = setTimeout( update, 500 );

			} );

			var element = editor.getWrapperElement();

			// toolbar

			var toolbar = document.getElementById( 'toolbar' );

			var buttonUpdate = document.createElement( 'button' );
			buttonUpdate.className = 'button';

			var checkbox = document.createElement( 'input' );
			checkbox.type = 'checkbox';

			if ( documents[ 0 ].autoupdate === true ) checkbox.checked = true;

			checkbox.style.margin = '-4px 4px -4px 0px';
			checkbox.addEventListener( 'click', function ( event ) {

				event.stopPropagation();

				documents[ 0 ].autoupdate = documents[ 0 ].autoupdate === false;

				localStorage.codeeditor = JSON.stringify( documents );

			}, false );
			buttonUpdate.appendChild( checkbox );
			buttonUpdate.appendChild( document.createTextNode( 'update' ) );

			buttonUpdate.addEventListener( 'click', function ( event ) {

				update();

			}, false );
			toolbar.appendChild( buttonUpdate );

			var buttonHide = document.createElement( 'button' );
			buttonHide.className = 'button';
			buttonHide.textContent = 'hide code';
			buttonHide.addEventListener( 'click', function ( event ) {

				toggle();

			}, false );
			toolbar.appendChild( buttonHide );

			var buttonMenu = document.createElement( 'button' );
			buttonMenu.className = 'button';
			buttonMenu.innerHTML = '<svg width="8" height="8"><path d="M 0,1.5 8,1.5 M 0,4.5 8,4.5 M 0,7.5 8,7.5"></svg>';
			buttonMenu.addEventListener( 'click', function ( event ) {

				menu.style.display = menu.style.display === '' ? 'none' : '';

			}, false );
			toolbar.appendChild( buttonMenu );

			toolbar.appendChild( document.createElement( 'br' ) );

			var menu = document.createElement( 'span' );
			menu.style.display = 'none';
			toolbar.appendChild( menu );

			var buttonSave = document.createElement( 'button' );
			buttonSave.className = 'button';
			buttonSave.textContent = 'save';
			buttonSave.addEventListener( 'click', function ( event ) {

				save();

			}, false );
			menu.appendChild( buttonSave );

			var buttonDownload = document.createElement( 'a' );
			buttonDownload.className = 'button';
			buttonDownload.style.display = 'none';
			buttonDownload.download = 'index.html';
			buttonDownload.textContent = 'download';
			menu.appendChild( buttonDownload );

			var buttonShare = document.createElement( 'button' );
			buttonShare.className = 'button';
			buttonShare.textContent = 'src';
			buttonShare.addEventListener( 'click', function ( event ) {

				var dom = document.createElement( 'input' );
				dom.value = '' + encode( editor.getValue() );
				dom.style.width = '400px';
				dom.style.padding = '5px';
				dom.style.marginTop = '20px';
				dom.style.border = '0px';

				popup.set( dom );
				popup.show();

				dom.focus();
				dom.select();

			}, false );
			menu.appendChild( buttonShare );

			var buttonReset = document.createElement( 'button' );
			buttonReset.className = 'button';
			buttonReset.textContent = 'reset';
			buttonReset.addEventListener( 'click', function ( event ) {

				if ( confirm( 'Are you sure?' ) === true ) {

					editor.setValue( defaultCode );
					save();

				}

			}, false );
			menu.appendChild( buttonReset );

			var buttonAbout = document.createElement( 'button' );
			buttonAbout.className = 'button';
			buttonAbout.textContent = 'about';
			buttonAbout.addEventListener( 'click', function ( event ) {

				var dom = document.createElement( 'div' );
				dom.style.width = '400px';
				dom.style.padding = '5px';
				dom.style.border = '0px';
				dom.style.textAlign = 'center';
				dom.innerHTML = '<h1>WEBGL中文网在线编辑器<\/h1><a href="http://www.webgl.com" target="_blank"></a>.<br>欢迎使用WebGL中文网为大家精心设计的在线编辑器！相信他能为您学习带来很大的帮助。<br/>请大家多多支持。谢谢。';
				popup.set( dom );
				popup.show();

			}, false );
			menu.appendChild( buttonAbout );


			// popup

			var popup = ( function () {

				var scope = this;

				var element = document.getElementById( 'popup' );
				element.style.display = 'none';

				var buttonClose = ( function () {

					var svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
					svg.setAttribute( 'width', 32 );
					svg.setAttribute( 'height', 32 );

					var path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
					path.setAttribute( 'd', 'M 9,12 L 11,10 L 15,14 L 19,10 L 21,12 L 17,16 L 21,20 L 19,22 L 15,18 L 11,22 L 9,20 L 13,16' );
					path.setAttribute( 'fill', 'rgb(235,235,235)' );
					svg.appendChild( path );

					return svg;

				} )();

				buttonClose.style.position = 'absolute';
				buttonClose.style.top = '5px';
				buttonClose.style.right = '5px';
				buttonClose.style.cursor = 'pointer';
				buttonClose.addEventListener( 'click', function ( event ) {

					scope.hide();

				}, false );
				element.appendChild( buttonClose );

				var content = document.createElement( 'div' );
				element.appendChild( content );

				var update = function () {

					element.style.left = ( ( window.innerWidth - element.offsetWidth ) / 2 ) + 'px';
					element.style.top = ( ( window.innerHeight - element.offsetHeight ) / 2 ) + 'px';

				};

				window.addEventListener( 'load', update, false );
				window.addEventListener( 'resize', update, false );

				//

				this.show = function () {

					element.style.display = '';
					update();

				};

				this.hide = function () {

					element.style.display = 'none';

				};

				this.set = function ( value ) {

					while ( content.children.length > 0 ) {

						content.removeChild( content.firstChild );

					}

					content.appendChild( value );

				};

				return this;

			} )();


			// events

			document.addEventListener( 'drop', function ( event ) {

				event.preventDefault();
				event.stopPropagation();

				var file = event.dataTransfer.files[ 0 ];

				documents[ 0 ].filename = file.name;
				documents[ 0 ].filetype = file.type;

				var reader = new FileReader();

				reader.onload = function ( event ) {

					editor.setValue( event.target.result );

				};

				reader.readAsText( file );

			}, false );

			document.addEventListener( 'keydown', function ( event ) {

				if ( event.keyCode === 83 && ( event.ctrlKey === true || event.metaKey === true ) ) {

					event.preventDefault();
					save();

				}

				if ( event.keyCode === 13 && ( event.ctrlKey === true || event.metaKey === true ) ) {

					update();

				}

				if ( event.keyCode === 27 ) {

					toggle();

				}

			}, false );


			// actions

			var update = function () {

				var value = editor.getValue();

				if ( validate( value ) ) {

					// remove previous iframe

					if ( preview.children.length > 0 ) {

						preview.removeChild( preview.firstChild );

					}

					//

					var iframe = document.createElement( 'iframe' );
					iframe.style.width = '100%';
					iframe.style.height = '100%';
					iframe.style.border = '0';
					preview.appendChild( iframe );

					var content = iframe.contentDocument || iframe.contentWindow.document;

					// workaround for chrome bug
					// http://code.google.com/p/chromium/issues/detail?id=35980#c12

					value = value.replace( '<script>', '<script>if ( window.innerWidth === 0 ) { window.innerWidth = parent.innerWidth; window.innerHeight = parent.innerHeight; }' );

					content.open();
					content.write( value );
					content.close();

				}

			};

			var errorLines = [];
			var widgets = [];

			var validate = function ( value ) {

				return editor.operation( function () {

					while ( errorLines.length > 0 ) {

						editor.removeLineClass( errorLines.shift(), 'background', 'errorLine' );

					}

					for ( var i = 0; i < widgets.length; i ++ ) {

						editor.removeLineWidget( widgets[ i ] );

					}

					widgets.length = 0;

					// remove html

					var string = '\n';
					var lines = value.split( '\n' );
					var lineCurrent = 0, lineTotal = lines.length;

					while ( lineCurrent < lineTotal && lines[ lineCurrent ].indexOf( '<script>' ) === -1 ) {

						string += '\n';
						lineCurrent ++;

					}

					var lineStart = lineCurrent ++;

					while ( lineCurrent < lineTotal && lines[ lineCurrent ].indexOf( '<\/script>' ) === -1 ) {

						string += lines[ lineCurrent ] + '\n';
						lineCurrent ++;

					}

					//

					try {

						var result = esprima.parse( string, { tolerant: true } ).errors;

						for ( var i = 0; i < result.length; i ++ ) {

							var error = result[ i ];

							var message = document.createElement( 'div' );
							message.className = 'esprima-error';
							message.textContent = error.message.replace(/Line [0-9]+: /, '');

							var lineNumber = error.lineNumber - 1;
							errorLines.push( lineNumber );

							editor.addLineClass( lineNumber, 'background', 'errorLine' );

							var widget = editor.addLineWidget(
								lineNumber,
								message
							);

							widgets.push( widget );

						}

					} catch ( error ) {

						var message = document.createElement( 'div' );
						message.className = 'esprima-error';
						message.textContent = error.message.replace(/Line [0-9]+: /, '');

						var lineNumber = error.lineNumber - 1;
						errorLines.push( lineNumber );

						editor.addLineClass( lineNumber, 'background', 'errorLine' );

						var widget = editor.addLineWidget(
							lineNumber,
							message
						);

						widgets.push( widget );

					}

					return errorLines.length === 0;

				});

			};

			var save = function () {

				documents[ 0 ].code = editor.getValue();

				localStorage.codeeditor = JSON.stringify( documents );

				var blob = new Blob( [ editor.getValue() ], { type: documents[ 0 ].filetype } );
				var objectURL = URL.createObjectURL( blob );

				buttonDownload.href = objectURL;

				var date = new Date();
				buttonDownload.download = documents[ 0 ].filename;

				buttonSave.style.display = 'none';
				buttonDownload.style.display = '';

			};

			var toggle = function () {

				if ( element.style.display === '' ) {

					buttonHide.textContent = 'show code';

					element.style.display = 'none';
					buttonUpdate.style.display = 'none';
					buttonShare.display = 'none';

				} else {

					buttonHide.textContent = 'hide code';

					element.style.display = '';
					buttonUpdate.style.display = '';
					buttonShare.display = '';

				}

			};

			update();

		</script>
	</body>
</html>
